package zm.irc.ioc.classCollector;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;

import zm.irc.ioc.annotation.Configuration;
import zm.irc.ioc.annotation.Service;
import zm.irc.ioc.pojo.WrapClass;

public class BeanClassFilter implements ClassEnrichment {
    private static final Logger log = Logger.getLogger(BeanClassFilter.class);

    public static final Set<Class<? extends Annotation>> BEAN_ANNOTATIONS = new HashSet<>();
    static{
        BEAN_ANNOTATIONS.add(Service.class);
        BEAN_ANNOTATIONS.add(Configuration.class);
        log.debug(String.format("The Initialization of Annotations "+
                                    "of IOC Beans finished.[%s]", BEAN_ANNOTATIONS));
    }

    @Override
    public Set<WrapClass> enrich(Set<WrapClass> originalClasses) {
        if(CollectionUtils.isEmpty(originalClasses)){
            log.warn("Classes is empty!");
            return Collections.emptySet();
        }
        log.debug("Before filter the size is : " + originalClasses.size() );
        Set<WrapClass> filteredClass = new HashSet<>();
        for(WrapClass wrapClass : originalClasses){
            if( isBeanClass(wrapClass)){
                filteredClass.add(wrapClass);
            }
        }
        log.debug("After filter the size is : " + filteredClass.size() );
        return filteredClass;
    }

    /**
     * <pre>
     * 1. Find out the first annotation of IOC bean.
     * 2. Return null ,if there is any IOC Bean annotation.
     * 3. Return the annotation.
     * </pre>
     */
    public static boolean isBeanClass(WrapClass wrapClass){
        if(wrapClass == null){
            return false;
        }
        Class<?> clazz = wrapClass.getOriginClass();
        if(clazz == null){
            return false;
        }
        Annotation[] annotations = clazz.getDeclaredAnnotations();

        if(annotations == null || annotations.length ==0){
            return false;
        }

        boolean isBeanClass = false;
        for(Annotation ann : annotations){
            if( !BEAN_ANNOTATIONS.contains(ann.annotationType())){
                continue;
            }
            if( ann instanceof Service){
                log.warn("Should be refactor.");
                Service bean = (Service) ann;
                wrapClass.setBeanId(bean.name());
                wrapClass.setSinglet(bean.isSinglet());
                isBeanClass = true;
            }else if( ann instanceof Configuration){
                Configuration bean = (Configuration) ann;
               
                wrapClass.setSinglet(bean.isSinglet());
                wrapClass.setCfgFileName(bean.cfgFileName());
                wrapClass.setLocalCfg(bean.isLocal());
                isBeanClass = true;
            }
        }

        return isBeanClass;
    }

    class BeanAnnotation{
        String beanName;
        Annotation anno;
        public String getBeanName() {
            return beanName;
        }
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
        public Annotation getAnno() {
            return anno;
        }
        public void setAnno(Annotation anno) {
            this.anno = anno;
        }

        
    }

}
